/*************************************************************************
	> File Name: pthread_race_mutual.c
	> Author: Angel Criss
	> Mail: abbytsing@gmail.com 
	> Created Time: Sun Jul 20 23:29:48 2014
 ************************************************************************/
/* 解决如下问题而使用互斥量 mutual exclusion
 * 不完美 例如: 如果不只一个线程在等待 pthread_mutex_unlock 解锁
 * 的互斥量，则无法判断时哪个线程得到解锁
 * */

// 当传入参数过大时，CPU会为两个线程分配时间片(线程间时平等的)
// 而每个线程在这个时间片中循环的次数时未知的，所有导致 global
// 变量的值有可能被覆盖 即:两个线程在竞争 CPU 资源

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>

static int global=0;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; // declare and initialize a mutual exclusion

void err(int s, char *fun)
{
    perror(fun);
    exit(s);
}

void *func(void *arg)
{
    int loop=*((int *)arg);
    int local,i,status;

    for(i=0;i<loop;i++)
    {
        if((status=pthread_mutex_lock(&lock))!=0) // lock 
            err(status,"mutex_lock");
        local=global;
        local++;
        global=local;
        if((status=pthread_mutex_unlock(&lock))!=0) // unlock
            err(status,"mutex_unlock");
    }

    return NULL;
}

int main(int argc, char *argv[])
{
    pthread_t pd1,pd2;
    void *res; // 未初始化 即: NULL
    int arg,s;

    arg=(argc>1)?atoi(argv[1]):1000;

    if((s=pthread_create(&pd1,NULL,func,&arg))!=0)
        err(s,"pthread_create1");
    if((s=pthread_create(&pd2,NULL,func,&arg))!=0)
        err(s,"pthread_create2");

    if((s=pthread_join(pd1,res))!=0)
        err(s,"pthread_join1");
    if((s=pthread_join(pd2,res))!=0)
        err(s,"pthread_join2");

    printf("the global is: %d\n",global);

    exit(EXIT_SUCCESS);
}
